package de.tum.in.eist.poll.server;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import au.com.bytecode.opencsv.CSVReader;
import au.com.bytecode.opencsv.CSVWriter;

import de.tum.in.eist.poll.shared.Feedback;
import de.tum.in.eist.poll.shared.Lecture;
import de.tum.in.eist.poll.shared.Lecturer;
import de.tum.in.eist.poll.shared.Student;
import de.tum.in.eist.poll.shared.User;

public class PollDataControl {

	/**
	 * Mapping from the lecture to the associated feedback.
	 */
	private static Map<Lecture, List<Feedback>> feedBackList;

	/**
	 * List of all Lectures.
	 */
	private static List<Lecture> lectures;

	final String path = "";
	final String lecturesFilename = path + "lectures.csv";
	final String feedbackFilename = path + "feedback.csv";

	/**
	 * load file from xml
	 */
	private void load() {
		feedBackList = new HashMap<Lecture, List<Feedback>>();
		lectures = new ArrayList<Lecture>();

		List<String[]> list;
		try {
			list = new CSVReader(new FileReader(lecturesFilename)).readAll();
			for (String[] line : list) {
				Lecture lecture = new Lecture(line[0], line[1], new Date(
						Long.parseLong(line[2])), new Lecturer(line[3], ""));
				String[] studentList = line[4].split("\\|");
				for (String student : studentList) {
					if (student.length() > 0)
						lecture.addStudent(new Student(student, ""));
				}
				lectures.add(lecture);
			}
		} catch (FileNotFoundException e) {
			lectures.add(new Lecture("ID0", "EIST", null, new Lecturer(
					"lecturer", "")));
			lectures.add(new Lecture("ID1", "INFO", null, new Lecturer("seidl",
					"")));
			lectures.get(0).openFeedback();
			lectures.get(1).openFeedback();
		} catch (IOException e) {
		}

		try {
			list = new CSVReader(new FileReader(feedbackFilename)).readAll();
			for (String[] line : list) {
				Lecture lecture = getLecture(line[0]);
				if (!feedBackList.containsKey(lecture)) {
					feedBackList.put(lecture, new ArrayList<Feedback>());
				}
				Feedback feedback = new Feedback();
				feedback.setDate(new Date(Long.parseLong(line[1])));
				feedback.setQuestion1(Integer.parseInt(line[2]));
				feedback.setQuestion2(line[3]);
				feedback.setQuestion2(line[4]);
				feedBackList.get(lecture).add(feedback);
			}
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
		}
	}

	/**
	 * save file to xml
	 */
	private void save() {// TODO users submitted speichern
		synchronized (feedBackList) {
			try {
				CSVWriter writer = new CSVWriter(new FileWriter(
						lecturesFilename));
				for (Lecture lecture : lectures) {
					Student[] students = lecture.getStudentsArray();
					StringBuilder studentList = new StringBuilder();
					for (Student student : students) {
						studentList.append(student.getName()).append("|");
					}
					String[] entries = {
							lecture.getLectureID(),
							lecture.getLectureTitle(),
							Long.toString(lecture.getCurrentLectureDate()
									.getTime()),
							lecture.getLecturer().getName(),
							studentList.toString() };

					writer.writeNext(entries);
				}
				writer.close();

				writer = new CSVWriter(new FileWriter(feedbackFilename));
				for (Lecture lecture : lectures) {
					if (feedBackList.containsKey(lecture)) {

						List<Feedback> feedbacks = feedBackList.get(lecture);
						for (Feedback feedback : feedbacks) {

							String[] entries = {
									lecture.getLectureID(),
									Long.toString(feedback.getDate().getTime()),
									Integer.toString(feedback.getQuestion1()),
									feedback.getQuestion2(),
									feedback.getQuestion3() };
							writer.writeNext(entries);
						}
					}
				}
				writer.close();

			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * constructor
	 */
	public PollDataControl() {
		if (feedBackList == null) {
			load();
		}
	}

	/**
	 * add new feedback from student
	 * @param feedback feedback to submit
	 * @param user
	 * @return success
	 */
	public boolean saveFeedback(Feedback feedback, Student user) {
		synchronized (feedBackList) {
			Lecture lecture = getLecture(feedback.getLecture().getLectureID());
			if (lecture == null || !lecture.isOpenForFeedback()
					|| lecture.containsStudent(user)) {
				return false;
			}
			feedback.setDate(lecture.getCurrentLectureDate());
			if (!feedBackList.containsKey(lecture)) {
				feedBackList.put(lecture, new ArrayList<Feedback>());
			}
			feedBackList.get(lecture).add(feedback);

			lecture.addStudent(user);
			save();
			synchronized (feedBackList.get(lecture)) {
				feedBackList.get(lecture).notifyAll();
			}
			return true;
		}
	}

	/**
	 * get feedback for a lecture
	 * @param lectureID
	 * @param date
	 * @return
	 */
	public List<Feedback> getFeedback(String lectureID, Date date) {
		synchronized (feedBackList) {
			Lecture lecture = getLecture(lectureID);
			ArrayList<Feedback> list = new ArrayList<Feedback>();
			if (!feedBackList.containsKey(lecture))
				return list;
			for (Feedback feedback : feedBackList.get(lecture)) {
				if (date == null || feedback.getDate().equals(date)) {
					list.add(feedback);
				}
			}
			return list;
		}
	}

	/**
	 * get lectures for wich the student can submit
	 * @param student
	 * @return
	 */
	public List<Lecture> getOpenLectures(Student student) {
		synchronized (feedBackList) {
			ArrayList<Lecture> openLectures = new ArrayList<Lecture>();
			for (Lecture lecture : lectures) {
				if (lecture.isOpenForFeedback()
						&& !lecture.containsStudent(student)) {
					openLectures.add(lecture);
				}
			}
			return openLectures;
		}
	}

	public List<Lecture> getLecturesOfLecturer(Lecturer lecturer) {
		synchronized (feedBackList) {
			ArrayList<Lecture> hisLectures = new ArrayList<Lecture>();
			for (Lecture lecture : lectures) {
				if (lecture.getLecturer().equals(lecturer)) {
					hisLectures.add(lecture);
				}
			}
			return hisLectures;
		}
	}

	/**
	 * get a lecture from id
	 * 
	 * @param lectureID
	 * @return
	 */
	public Lecture getLecture(String lectureID) {
		synchronized (feedBackList) {
			for (Lecture lecture : lectures) {
				if (lecture.getLectureID().equals(lectureID)) {
					return lecture;
				}
			}
			return null;
		}
	}

	public List<Date> getLectureDates(String lectureID) {
		synchronized (feedBackList) {
			Lecture lecture = getLecture(lectureID);
			ArrayList<Date> list = new ArrayList<Date>();
			if (feedBackList.containsKey(lecture)) {
				for (Feedback feedback : feedBackList.get(lecture)) {
					if (list.contains(feedback.getDate())) {
						list.add(feedback.getDate());
					}
				}
			}
			return list;
		}
	}

	/**
	 * wait for feedback, for push nofication
	 * @param lectureID
	 * @return
	 */
	public void waitForFeedback(String lectureID) {
		Lecture lecture = getLecture(lectureID);
		synchronized (feedBackList.get(lecture)) {
			do {
				try {
					feedBackList.get(lecture).wait();
				} catch (InterruptedException e) {
				}
			} while (true);
		}
	}
}
